﻿using System;

namespace Skybot.Extension
{
    /// <summary>
    /// 扩展方法类
    /// </summary>
    public static class Extensions
    {
        #region AllByteEquals




        #endregion

        

        #region 16进制字符串和字节数组互相转换：HexToByteArray|ByteArrayToHex

        /// <summary>
        /// 16进制字符串转换为对应字节数组
        /// 注意：一个字节是二个字符
        /// </summary>
        /// <param name="hexText">16进制字符串，必须是2的整数倍</param>
        /// <returns>
        ///    16进制字符串对应的字节数组
        /// </returns>
        public static byte[] HexToByteArray(this string hexText)
        {
            //一个字节是2个字符
            byte[] byteArray = new byte[hexText.Length / 2];

            for (int i = 0; i < hexText.Length; i += 2)
            {
                byteArray[i / 2] = Convert.ToByte(hexText.Substring(i, 2), 16);
            }

            return byteArray;
        }



        #endregion

        #region 16进制和2进制字符串互转：HexToBinary|BinaryToHex

        /// <summary>
        /// 16进制字符串形式转换为2进制字符串形式
        /// </summary>
        /// <param name="text"></param>
        /// <returns>
        /// </returns>
        public static string HexToBinary(this string text)
        {
            return Convert.ToString(Convert.ToInt32(text, 16), 2);
        }

        /// <summary>
        /// 2进制字符串形式转换为16进制字符串形式
        /// </summary>
        public static string BinaryToHex(this string txt)
        {
            return Convert.ToString(Convert.ToInt32(txt, 2), 16);
        }

        #endregion

        #region ByteIndexOf

        /// <summary>
        ///  查询一个byte数组在别一个byte数组中的位置,-1表示不存在
        /// </summary>
        /// <param name="searched">查询数据</param>
        /// <param name="find">数据源</param>
        /// <returns>int</returns>
        public static int ByteIndexOf(this byte[] searched, byte[] find)
        {
            return ByteIndexOf(searched, find, 0);
        }

        /// <summary>
        /// 查询一个byte数组在别一个byte数组中的位置,-1表示不存在
        /// </summary>
        /// <param name="searched">查询数据</param>
        /// <param name="find">数据源</param>
        /// <param name="start">数据源起始位置查询</param>
        /// <returns>int</returns>
        public static int ByteIndexOf(this byte[] searched, byte[] find, int start)
        {
            return ByteIndexOf(searched, find, start, searched.Length);
        }

        /// <summary>
        /// 查询一个byte数组在别一个byte数组中的位置,-1表示不存在
        /// </summary>
        /// <param name="searched">查询数据</param>
        /// <param name="find">数据源</param>
        /// <param name="start">数据源起始位置查询</param>
        /// <param name="count">查询总长度</param>
        /// <returns>int</returns>
        public static int ByteIndexOf(this byte[] searched, byte[] find, int start, int count)
        {
            // ReSharper disable TooWideLocalVariableScope
            //是否找到匹配字节数组find，默认为false
            bool matched;
            //find结束索引号
            int end = find.Length - 1;
            int skip;//默认为0
            //要比较的个数
            int fcount = start + count - find.Length;
            // ReSharper restore TooWideLocalVariableScope

            for (int index = start; index <= fcount; ++index)
            {
                skip = 0;
                matched = true;
                if (find[0] != searched[index] || find[end] != searched[index + end])
                    continue;

                skip++;

                if (end > 10)
                    if (find[skip] != searched[index + skip] || find[end - skip] != searched[index + end - skip])
                        continue;
                    else
                        skip++;
                for (int subIndex = skip; subIndex < find.Length - skip; ++subIndex)
                {
                    if (find[subIndex] != searched[index + subIndex])
                    {
                        matched = false;
                        break;
                    }
                }
                if (matched)
                {
                    return index;
                    //return index + find.Length - 1;
                }
            }

            return -1;
        }

        #endregion

        #region ByteArray2HexString

        /// <summary>
        /// 得到字节数组的16进制字符串,以空格间隔
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="split">分隔符  char 一个字符</param>
        /// <returns></returns>
        public static string ByteArray2HexString(this byte[] bytes, string @split = " ")
        {
            //StringBuilder sb = new StringBuilder(bytes.Length * 2);
            //foreach (byte bt in bytes)
            //{
            //    sb.Append(bt.ToString("X2") + @split);
            //}

            //return sb.ToString();

            return ByteArray2Hex(bytes, @split[0]);

        }

        /// <summary>
        ///     字节数组转换为16进制字符串
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="offset">开始索引</param>
        /// <param name="length">转换个数</param>
        /// <param name="split">分隔符</param>
        public static string ByteArray2HexString(this byte[] bytes, int offset, int length, string @split = " ")
        {

            return ByteArray2Hex(bytes, offset, length, @split[0]);
        }

        #region 提供的字符串转换代码
        /// <summary>
        /// 将字节数组转换为文本，默认使用一个空格隔离（高性能版本）
        /// </summary>
        /// <param name="byteArray">字节数组</param>
        /// <param name="splitChar">分割字符</param>
        /// <returns></returns>
        public static string ByteArray2Hex(byte[] byteArray, char splitChar)
        {
            if (byteArray == null) throw new ArgumentNullException("byteArray");

            if (byteArray.Length == 0) return string.Empty;

            int chArrayLength = byteArray.Length * 3;

            char[] chArray = new char[chArrayLength];
            int index = 0;
            for (int i = 0; i < chArrayLength; i += 3)
            {
                byte b = byteArray[index++];
                //b/16得到16进制字符串形式AB的A,小于10，则应该是'0' + A，
                chArray[i] = GetHexValue(b / 16);
                chArray[i + 1] = GetHexValue(b % 16);
                chArray[i + 2] = splitChar;
            }
            return new String(chArray, 0, chArray.Length - 1);
        }
        /// <summary>
        /// 将字节数组转换为文本，默认使用一个空格隔离（高性能版本）
        /// </summary>
        /// <param name="byteArray">字节数组</param>
        /// <param name="splitChar">分割字符</param>
        /// <param name="offset">字节数组偏移量</param>
        /// <param name="length">需要处理数组长度</param>
        /// <returns></returns>
        public static string ByteArray2Hex(byte[] byteArray, int offset, int length, char splitChar)
        {
            if (byteArray == null) throw new ArgumentNullException("byteArray");

            if (byteArray.Length - (offset + length) == 0) return string.Empty;

            int chArrayLength = length * 3;

            char[] chArray = new char[chArrayLength];
            int index = offset;
            for (int i = 0; i < chArrayLength; i += 3)
            {
                byte b = byteArray[index++];
                //b/16得到16进制字符串形式AB的A,小于10，则应该是'0' + A，
                chArray[i] = GetHexValue(b / 16);
                chArray[i + 1] = GetHexValue(b % 16);
                chArray[i + 2] = splitChar;
            }
            return new String(chArray, 0, chArray.Length - 1);
        }
        /// <summary>
        /// 16进制字符串转换为对应字节数组（16进制中的字符应该是大写字母）
        /// 注意：一个字节是二个字符
        /// </summary>
        public static byte[] Hex2ByteArray(string hexStr)
        {
            if (hexStr == null) throw new ArgumentNullException("hexStr");

            if (hexStr.Length == 0) return new byte[0];

            //一个字节是2个字符(1个字节8个bit，1个16进制字符是4个bit，所以1个字节对应2个16进制字符)
            byte[] byteArray = new byte[hexStr.Length / 2];

            for (int ndx = 0; ndx < hexStr.Length; ndx += 2)
            {
                byteArray[ndx / 2] = (byte)(GetIntValue(hexStr[ndx]) * 16 + GetIntValue(hexStr[ndx + 1]));
            }

            return byteArray;
        }

        /// <summary>
        /// 得到字节对应的16进制字符（有二个）
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        internal static char GetHexValue(int i)
        {
            if (i < 10)
            {
                return (char)(i + '0');
            }

            return (char)(i - 10 + 'A');
        }

        public static int GetIntValue(char charX)
        {
            if (charX <= '9')
            {
                //数字从0的ASCII：48
                return (charX - 48);
            }

            //数组从A的ASCII:65
            return (charX - 65) + 10;
        }
        #endregion

        #endregion


        /// <summary>
        /// 格式化字符串，等同于 string.Format()
        ///   如果格式化参数args的字符串形式字符数平均超过8个字符很多，可以考虑使用FormatWith
        ///   如果计算前就已经明确格式化后的字符串长度，请用带容量参数的FormatWith
        /// </summary>
        /// <param name="format">要格式化的字符串</param>
        /// <param name="args">格式化需要的参数{0}{N}</param>
        /// <returns>
        ///   格式化后的文本
        /// </returns>
        public static string FormatString(this string format, params object[] args)
        {
            return String.Format(format, args);
        }

        /// <summary>
        /// 判断二个字符串是否相同
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="target">目标字符串</param>
        /// <param name="ignoreCase">是否区分大小写</param>
        /// <returns></returns>
        public static bool EqualTo(this string source, string target, StringComparison ignoreCase)
        {
            return String.Compare(source, target, ignoreCase) == 0;
        }

        /// <summary>
        /// 判断二个字符串是否相同，不区分大小写
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="target">目标字符串</param>
        /// <returns></returns>
        public static bool EqualTo(this string source, string target)
        {
            return String.Compare(source, target, StringComparison.OrdinalIgnoreCase) == 0;
        }
    }
}